#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include "include/structs.h"
#include "include/params.h"


CriptoType getCriptoType(const char * arg);
CriptoMode getCriptoMode(const char * arg);
StegoMode getStegoMode(const char * arg);

int
getParams (int argc, char * argv[], Params *params)
{
	int c;

	static struct option long_options[] =
	{
		{"out", required_argument, NULL, 0},
		{"in", required_argument, NULL, 1},
		{"pass", required_argument, NULL, 'p'},
		{"a", required_argument, NULL, 'a'},
		{"m", required_argument, NULL, 'm'},
		{"embed", no_argument, NULL, 2},
		{"extract", no_argument, NULL, 3},
		{"p", required_argument, NULL, 4},
		{"steg", required_argument, NULL, 's'},
		{0, 0, 0, 0}
	};
	/* getopt_long stores the option index here. */

	int option_index = 0;

	while ( (c = getopt_long_only (argc, argv, "",long_options, &option_index)) != -1 )
	{
		switch (c)
		{
			case 0:
				/* Means -out found. */
				if (optarg){
					strcpy(params->out, optarg);
				}
				break;

			case 1:
				/* Means -in found! */
				if (optarg != NULL){
					strcpy(params->in, optarg);
				}
				break;
			case 2:
				if (params -> sop == EXTRACT)
				{
					params -> sop = UNDEFINED;
				}
				else
				{
					params -> sop = EMBED;
				}
				break;
			case 3:
				if (params -> sop == EMBED)
				{
					params -> sop = UNDEFINED;
				}
				else
				{
					params -> sop = EXTRACT;
				}
				break;

			case 'p':
				strcpy(params->pass, optarg);
				break;

			case 'a':
				if (optarg != NULL)
				{
					params -> a = getCriptoType(optarg);
				}
				break;

			case 'm':
				if (optarg != NULL)
				{
					params -> m = getCriptoMode(optarg);
				}
				break;

			case 's':
				if (optarg != NULL)
				{
					params -> s = getStegoMode(optarg);
				}
				break;
			case 4:
				if (optarg != NULL)
				{
					strncpy(params -> p, optarg, strlen(optarg));
					params -> p[strlen(optarg)] = '\0';
				}
				break;
			case '?':
				printf("ERROR in getopt_long\n");
				exit(-1);

			default:
				exit (-1);
			}
	}

	/* Print any remaining command line arguments (not options). */
	if (optind < argc)
	{
		printf ("Argumento/s no reconocidos: ");
		while (optind < argc)
			printf ("%s ", argv[optind++]);
		putchar ('\n');
	}

	int good=0;
	good = validateParams(params);

	if(!good)
	{
		printf("Error en los comandos\n");
	}

	return good;
}

void
initParams(Params * params)
{
	strcpy(params -> in, "");
	strcpy(params -> out, "");
	params -> pass[0] = '\0';
	params -> p[0] = '\0';
	params -> a = AES128; 	// default aes128 criptoType
	params -> m = CBC;		// default cbc criptoMode
	params -> s = NONE;
	params -> sop = UNDEFINED;
}

int
validateParams(Params * params)
{
	// Ahora el parmetro -in no puede venir si el modo de operacon es EXTRACT
	if( (strlen(params->in) == 0 && params -> sop == EMBED) || (strlen(params->in) != 0 && params -> sop == EXTRACT)
			|| strlen(params->out) == 0	|| params -> p[0] == '\0' || params -> s == NONE || params -> sop == UNDEFINED)
	{
		return 0;
	}

	return 1;
}

CriptoType
getCriptoType(const char * arg)
{
	int i;
	const char * criptoNames[CRIPTOQTY] = {"aes128","aes192","aes256","des"};
	CriptoType criptotypes[CRIPTOQTY] = {AES128, AES192, AES256, DES};
	CriptoType criptotype = AES128;

	if (arg != NULL)
	{
		for (i = 0 ; i < CRIPTOQTY ; i++)
		{
			if (strncmp(arg,criptoNames[i],strlen(criptoNames[i])) == 0)
			{
				criptotype = criptotypes[i];
				break;
			}
		}
	}

	return criptotype;
}

CriptoMode
getCriptoMode(const char * arg)
{
	int i;
	const char * criptoModeNames[MODEQTY] = {"ecb","cfb","ofb","cbc"};
	CriptoMode criptomodes[MODEQTY] = {ECB,CFB,OFB,CBC};
	CriptoMode criptomode = CBC;

	if (arg != NULL)
	{
		for (i = 0 ; i < MODEQTY ; i++)
		{
			if (strncmp(arg,criptoModeNames[i],strlen(criptoModeNames[i])) == 0)
			{
				criptomode = criptomodes[i];
				break;
			}
		}
	}

	return criptomode;
}

StegoMode
getStegoMode(const char * arg)
{
	int i;
	const char * stegoModeNames[STEGOMODEQTY] = {"lsb1", "lsb4", "lsbe"};
	StegoMode stegomodes[STEGOMODEQTY] = {LSB1, LSB4, LSBE};
	StegoMode stegomode = NONE;

	if (arg != NULL)
	{
		for (i = 0 ; i < STEGOMODEQTY ; i++)
		{
			if (strncmp(arg, stegoModeNames[i], strlen(stegoModeNames[i])) == 0)
			{
				stegomode = stegomodes[i];
				break;
			}
		}
	}

	return stegomode;
}
